// 
//  Main.cs
//  
//  Author:
//       Ray Shaw <demogodyou@gmail.com>
// 
//  Copyright (c) 2009 Ray Shaw(xiaolei)
// 
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 
using System;
using SharpNote.Core.Config;
using SharpNote.Core.Entity;
using SharpNote.Core.Data;
using SharpNote.Core.Command;
using System.Text;

namespace SharpNoteConsole
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			Console.Title = "SharpNote";

			//System model, use core database.
			SysConfig sysConfig = SysConfig.GetInstance ();
			sysConfig.DbFileName = System.IO.Path.Combine (System.IO.Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "Data")
				                                           , "SharpNote.db");
			sysConfig.DbPassword = "";
			
			CommandFactory cmdFactory = new CommandFactory();

			if (!System.IO.File.Exists (sysConfig.DbFileName)) {
				Console.WriteLine (string.Format ("Can not find SharpNot database file: {0}.", sysConfig.DbFileName));
				Console.ReadLine ();
				return;
			}
			
			//welcome
			Console.WriteLine (string.Format ("SharpNote [Version: {0}]\nCopyleft(C) 2009, Ray Shaw(demogodyou@gmail.com).\n", "1.0"));

			//no user, create new user at first.
			if (UserInfo.GetRowCount<UserInfo> () == 0) {
				Console.WriteLine ("Welcome to use SharpNote! \nTo start SharpNote, we should create a new user at first.\n");

				if (CreateNewUser ()) {
					Console.WriteLine (">>Create new user success.");
				} else {
					Console.WriteLine (">>Create new user failed.");
					Console.ReadLine();
					return;
				}
			}

			//verification of identity.
			Console.WriteLine ("\nSharpNote will verify your identity at first.");

			UserInfo signInUserInfo = null;
			bool signInOk = SignIn(out signInUserInfo);
			int failSignInCount = 0;
			
			while(!signInOk)
			{
			   signInOk = SignIn(out signInUserInfo);	
			   if(!signInOk){ failSignInCount++; }
			}
			
			//Switch to user model, use user database.
			//set user database file name.
			sysConfig.DbFileName =System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
			                                              "Data"), signInUserInfo.Id), signInUserInfo.Id + ".db");
			//set current signed in userInfo.
			sysConfig.SignInUserInfo = signInUserInfo;
			
			//Come in SharpNote envirment.
			Console.Clear();
			Console.Write ("SharpNote>");
			string command = string.Empty;
			Invoker invoker =  new Invoker();
			
			while (!command.Equals ("quit", StringComparison.CurrentCultureIgnoreCase)
			       && !command.Equals ("exit", StringComparison.CurrentCultureIgnoreCase)) {
				command = Console.ReadLine();
				
				if(command.Trim().Length > 0)
				{
					//quit.
					if(command.Equals ("quit", StringComparison.CurrentCultureIgnoreCase)
					   || command.Equals ("exit", StringComparison.CurrentCultureIgnoreCase)) 
					{ 
						return;
					}
					
					//clear all displayed text.
					if(command.Equals ("clear", StringComparison.CurrentCultureIgnoreCase)
					   || command.Equals ("cls", StringComparison.CurrentCultureIgnoreCase)) 
					{ 
						Console.Clear();
						Console.Write("SharpNote>");
						continue;
					}
					
					string[] array = CommandLineParser.Parse(command);
					string[] parameters = new string[0];
					
					CommandBase cmd = cmdFactory.GetCommand(array[0]);
					if(cmd == null){
					    Console.WriteLine(">>Invalid command.");
						Console.Write ("SharpNote>");
						
						continue;
					}
					
					if(array.Length >= 0)
					{
					   	invoker.SetCommand(cmd);
						
						if(array.Length > 1)
						{
							parameters = new string[array.Length - 1];
						    Array.Copy(array, 1, parameters, 0, parameters.Length);
						}
						
						object result = false;
						invoker.ExecuteCommand(ref result, parameters);
					}
				}
				
				Console.Write ("SharpNote>");
			}

		}

		/// <summary>
		///  Create new user.
		/// </summary>
		/// <returns>if success.
		/// A <see cref="System.Boolean"/>
		/// </returns>
		private static bool CreateNewUser ()
		{
			string userName = string.Empty;
			while (userName == string.Empty) {
				Console.Write ("Please input the new user name: ");
				userName = Console.ReadLine ();
			}

			string password = string.Empty;
			while (password == string.Empty) {
				Console.Write ("Please input the sign in password of the new user: ");
				password = Console.ReadLine ();
			}

			if (!string.IsNullOrEmpty (userName)) {
				UserInfo userInfo = new UserInfo ();
				userInfo.Id = Guid.NewGuid ().ToString ();
				userInfo.UserName = userName;
				userInfo.SetSignInPassword (password);
				userInfo.SetPrivateKey (password, Guid.NewGuid ().ToString ());
				userInfo.SetDefaultKey (password, Guid.NewGuid ().ToString ());

				try {
					return UserInfo.CreateNewUser(userInfo);
				} catch (Exception ex) {
					Console.WriteLine (">>Create new user failed. Detail: ");
					Console.WriteLine (ex.ToString ());
					return false;
				}
			}

			return false;
		}
		
		/// <summary>
		///  Sign in.
		/// </summary>
		/// <returns>
		/// A <see cref="System.Boolean"/>
		/// </returns>
		private static bool SignIn(out UserInfo signedInUserInfo)
		{
			signedInUserInfo = null;
			
			//input user name.
			string userName = string.Empty;
			while (userName == string.Empty) {
				Console.Write ("Please input your user name: ");
				userName = Console.ReadLine ();
			}

			//input password
			string password = string.Empty;
			Console.Write ("Please input password: ");
			password = Console.ReadLine ();
			
			bool isEmpty = true;
			UserInfo userInfo = DbObjectMappingHelper.Query<UserInfo>("select * from UserInfo where UserName = @userName",
			                                                          out isEmpty,
			                                                          DataAccessService.CreateDbParameter("@userName", System.Data.DbType.String, userName));
			if(!string.IsNullOrEmpty(userInfo.UserName))
			{
			  	if(userInfo.IsSignInPasswordEquals(password))
				{
					signedInUserInfo = userInfo;
					return true;
				}else
				{
				    Console.WriteLine(">>Wrong user name or password.\n");	
				}
			}else
			{
			    Console.WriteLine(">>Wrong user name or password.\n");	
			}
			
			return false;
		}
	}
}
